package cn.semcorp.zhuhaizj.controller;

import cn.semcorp.zhuhaizj.common.Common;
import cn.semcorp.zhuhaizj.exception.ServiceException;
import cn.semcorp.zhuhaizj.mapper.TrainingMapper;
import cn.semcorp.zhuhaizj.mapper.UserMapper;
import cn.semcorp.zhuhaizj.pojo.dto.FlowerUserDTO;
import cn.semcorp.zhuhaizj.pojo.dto.TrainingDataDTO;
import cn.semcorp.zhuhaizj.pojo.vo.TrainingDataVO;
import cn.semcorp.zhuhaizj.repo.IRedisRepository;
import cn.semcorp.zhuhaizj.restful.JsonResult;
import cn.semcorp.zhuhaizj.restful.ResponseCode;
import cn.semcorp.zhuhaizj.services.impl.AccountingServiceImpl;
import cn.semcorp.zhuhaizj.services.impl.UtilizationServiceImpl;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Slf4j
@RestController
@Api(tags = "内部接口")
@RequestMapping("/out")
public class TestController {
    @Autowired
    private TrainingMapper trainingMapper;
    @Autowired
    private AccountingServiceImpl accountingService;
    @Autowired
    public UtilizationServiceImpl utilizationService;
    @Autowired
    public UserMapper userMapper;
    @Autowired
    private IRedisRepository redisRepository;

    @PostMapping("/update/flower")
    @ApiOperation("培训-修改花名册人入职时间格式")
    @ApiOperationSupport(order = 101)
    public JsonResult updateFlower(){
        List<FlowerUserDTO> flowerUserDTOS = trainingMapper.selectFlowerList();
        for (FlowerUserDTO flowerUserDTO : flowerUserDTOS) {
            if (flowerUserDTO.getInputTime().contains("/")){
                trainingMapper.updateTest(flowerUserDTO.getId(),formatterLocalDate(flowerUserDTO.getInputTime()));
            }
        }
        return JsonResult.ok("success");
    }

    @PostMapping("/update/course")
    @ApiOperation("培训-修改花课程列表时间格式")
    @ApiOperationSupport(order = 102)
    public JsonResult updateCourse(){
        List<TrainingDataVO> trainingDataDTOS = trainingMapper.selectTrainingClassList();
        for (TrainingDataVO trainingDataDTO : trainingDataDTOS) {
            if (trainingDataDTO.getMakeDate().contains("/")){
                trainingMapper.updateFlowerUserById(trainingDataDTO.getId(),formatterLocalDate(trainingDataDTO.getMakeDate()));
            }
        }
        return JsonResult.ok("success");
    }

    @PostMapping("/insert/assessModel")
    @ApiOperation("培训-添加违反类型")
    @ApiOperationSupport(order = 103)
    @ApiImplicitParam(name = "model",value = "考核类型",required = true)
    public JsonResult insertAssessModel(String model){
        try {
            trainingMapper.insertAssessModel(model);
            return JsonResult.ok("成功!");
        }catch (Throwable e){
            return JsonResult.failed(e.getMessage());
        }
    }


    /**
     * 内部接口 - 培训 - 添加课程的培训时段
     * @return
     */
    @PostMapping("/insert/trainingDate")
    @ApiOperation("培训-添加课程的培训时段")
    @ApiOperationSupport(order = 104)
    @ApiImplicitParam(name = "date", value = "时段")
    public JsonResult insertTrainingDate(String date){
        try{
            trainingMapper.insertTrainingDate(date);
            return JsonResult.ok("成功!");
        }catch (Throwable e){
            return JsonResult.failed(e.getMessage());
        }
    }

    /**
     * 内部接口 - 培训 - 添加课程的教育类型
     * @return
     */
    @PostMapping("/insert/educationModel")
    @ApiOperation("培训-添加课程的教育类型")
    @ApiOperationSupport(order = 105)
    @ApiImplicitParam(name = "model", value = "教育类型")
    public JsonResult insertEducationModel(String model){
        try{
            trainingMapper.insertEducationModel(model);
            return JsonResult.ok("成功!");
        }catch (Throwable e){
            return JsonResult.failed(e.getMessage());
        }
    }

    /**
     * 内部接口 - 培训 - 添加课程的培训类型
     * @return
     */
    @PostMapping("/insert/trainingModel")
    @ApiOperation("培训-添加课程的培训类型")
    @ApiOperationSupport(order = 106)
    @ApiImplicitParam(name = "model", value = "培训类型")
    public JsonResult insertTrainingModel(String model){
        try{
            trainingMapper.insertTrainingModel(model);
            return JsonResult.ok("成功!");
        }catch (Throwable e){
            return JsonResult.failed(e.getMessage());
        }
    }

    /**
     * 内部接口 - 培训 - 添加课程类型
     * @return
     */
    @PostMapping("/insert/classModel")
    @ApiOperation("培训-添加课程类型")
    @ApiOperationSupport(order = 107)
    @ApiImplicitParam(name = "model", value = "课程类型")
    public JsonResult insertClassModel(String model){
        try{
            trainingMapper.insertClassModel(model);
            return JsonResult.ok("成功!");
        }catch (Throwable e){
            return JsonResult.failed(e.getMessage());
        }
    }

    /**
     * 导入课程
     * @param sheetUrl
     * @return
     */
    @PostMapping("/insert/class/training")
    @ApiOperation("培训-导入课程列表")
    @ApiOperationSupport(order = 108)
    public JsonResult insertTrainingClassList(
            @RequestParam(defaultValue = "/Users/woaini/Desktop/培训课程导入模板.xlsx") String sheetUrl) {
        Integer rows = utilizationService.quartzInsertClassDate(sheetUrl);
        return JsonResult.ok("培训课程数据导入成功,共导入"+rows+"条记录!");
    }








    /**
     * 内部接口-账务-添加非量产原料名
     * @param materials
     * @return
     */
    @PostMapping("/add/isMall")
    @ApiOperation("账务-添加非量产原料名")
    @ApiOperationSupport(order = 201)
    @ApiImplicitParam(name = "materials",value = "原料名",required = true)
    public JsonResult addIsMall(String materials){
        try{
            return JsonResult.ok(accountingService.addIsMassProduct(materials));
        }catch (Throwable e){
            return JsonResult.failed(e.getMessage());
        }
    }




    @PostMapping("/insert/admin")
    @ApiOperation("用户-添加管理员账号")
    @ApiOperationSupport(order = 301)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username",value = "用户名",required = true),
            @ApiImplicitParam(name = "password",value = "密码",required = true),
            @ApiImplicitParam(name = "authority",value = "权限",required = true)
    })
    public JsonResult insertAdmin(String username, String password,String authority){
        try{
            userMapper.insertAdmin(username,password,authority);
            return JsonResult.ok("添加管理员成功!");
        } catch (Throwable e) {
            return JsonResult.failed(e.getMessage());
        }
    }

    /**
     * 上传用户图像(内部接口)
     */
    @PostMapping("/uploadAvatar/{username}")
    @ApiOperation("用户-上传管理用户头像")
    @ApiOperationSupport(order = 301)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username",value = "用户名",required = true),
            @ApiImplicitParam(name = "file",value = "图像",required = true),
    })
    public JsonResult uploadAvatar(@PathVariable String username,@RequestBody MultipartFile file) {
        try{
            String base64 = Base64.encodeBase64String(file.getBytes());
            userMapper.uploadAvatar(username,base64);
            return JsonResult.ok("上传成功!");
        }catch (Throwable e){
            return JsonResult.failed(e.getMessage());
        }
    }








    /** 重要接口
     * 上传涂布产出表
     */
    @PostMapping("/update/coating")
    @ApiOperation("利用率-导入涂布产出")
    @ApiOperationSupport(order = 401)
    public JsonResult updateCoating(
            @RequestParam(defaultValue = "/Users/woaini/Desktop/涂布产出导入模板.xlsx") String sheetUrl){
        List<Integer> rows = utilizationService.quartzInsertCoatingDate(sheetUrl);
        return JsonResult.ok("涂布产出数据导入成功,分"+rows.get(1)+"批,共导入"+rows.get(0)+"条记录!");
    }

    /** 重要接口
     * 上传制浆领用表
     */
    @PostMapping("/update/pulping")
    @ApiOperation("利用率-导入制浆领用")
    @ApiOperationSupport(order = 402)
    public JsonResult updatePulping(
            @RequestParam(defaultValue = "/Users/woaini/Desktop/制浆领用导入模板.xlsx") String sheetUrl){
        List<Integer> rows =  utilizationService.quartzInsertPulpingDate(sheetUrl);
        return JsonResult.ok("制浆领用数据导入成功,分"+rows.get(1)+"批,共导入"+rows.get(0)+"条记录!");
    }

    /** 重要接口
     * 同步-> 生成利用率- 班次/日次/低
     */
    @PostMapping("/sync/utilization")
    @ApiOperation("利用率-时间段同步")
    @ApiOperationSupport(order = 403)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "start",value = "起始时间",required = true),
            @ApiImplicitParam(name = "end",value = "结束时间",required = true)
    })
    public JsonResult syncUtilization(String start,String end){
        if (start.equals(end)){
            utilizationService.quartzInsertShiftUtilization(start);
            utilizationService.quartzInsertDayUtilization(start);
            utilizationService.quartzInsertLowUtilizationDay(start);
            return JsonResult.ok("时间点:"+start+"同步成功!");
        }

        Pattern pattern = Pattern.compile(Common.patternStr);
        Matcher matcherStart = pattern.matcher(start);
        Matcher matcherEnd = pattern.matcher(end);
        if (!matcherStart.matches() || !matcherEnd.matches()){
            throw new ServiceException(ResponseCode.BAD_REQUEST,"日期格式错误,请提供yyyy-mm-dd");
        }

        LocalDate startDate = LocalDate.parse(start);
        LocalDate endDate = LocalDate.parse(end);
        if (endDate.isBefore(startDate)){
            throw new ServiceException(ResponseCode.BAD_REQUEST,"开始日期不能位于结束日期之后!");
        }

        List<String> dateList = new ArrayList<>();
        while (!startDate.isAfter(endDate)) {
            dateList.add(String.valueOf(startDate));
            startDate = startDate.plusDays(1);
        }

        for (String date : dateList) {
            utilizationService.quartzInsertShiftUtilization(date);
            utilizationService.quartzInsertDayUtilization(date);
            utilizationService.quartzInsertLowUtilizationDay(date);
        }
        return JsonResult.ok("时间段:"+start+"至"+end+"同步成功!");
    }

    /**
     * 内部接口 - 添加浆料-固含量数据
     * @param
     * @return
     */
    @GetMapping("/add/solids")
    @ApiOperation("利用率-添加浆料固含量")
    @ApiOperationSupport(order = 404)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "slurryName",value = "浆料名称",required = true),
            @ApiImplicitParam(name = "model",value = "浆料类型",required = true),
            @ApiImplicitParam(name = "solids",value = "固含量",required = true)
    })
    public JsonResult addSolids(String slurryName,String model,String solids){
        utilizationService.addSolids(slurryName,model,solids);
        return JsonResult.ok("添加成功!");
    }


    /**
     * 内部接口 - 同步redis人员信息
     * @param
     * @return
     */
    @GetMapping("/sync/redis/all")
    @ApiOperation("redis-全量同步")
    @ApiOperationSupport(order = 501)
    public JsonResult syncFlowerList(){
        try{
            redisRepository.deleteFlowerList();
            redisRepository.deleteFlower();
            redisRepository.deleteCoatingWorkshop();
            redisRepository.deleteSchema();
            redisRepository.deleteCountStudy();
            return JsonResult.ok("success");
        }catch (Throwable e){
            return JsonResult.failed(e.getMessage());
        }
    }

    @GetMapping("/sync/redis/roster")
    @ApiOperation("redis-同步人员列表数据")
    @ApiOperationSupport(order = 502)
    public JsonResult syncRedisRoster(){
        try{
            redisRepository.deleteFlowerList();
            redisRepository.deleteFlower();
            return JsonResult.ok("人员信息同步成功!");
        }catch (Throwable e){
            return JsonResult.failed(e.getMessage());
        }
    }

    @GetMapping("/test")
    @ApiOperation("测试-异常抛出")
    public String test() {
        // 故意抛出异常以测试全局异常处理器
        throw new RuntimeException("Test exception");
    }



    public static String formatterLocalDate(String date){

        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy/M/d");
        LocalDate localDate = LocalDate.parse(date, inputFormatter);

        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return localDate.format(outputFormatter);
    }
}
